﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Pixysoft.Framework.Configurations.Core
{
    class HtmlTableCollection : IHtmlTableCollection
    {
        int index = -1;

        int nestlevel = 0;

        List<IHtmlTable> tables;

        public HtmlTableCollection(IHtmlNodesCollection nodes, string path, int nestlevel)
        {
            tables = new List<IHtmlTable>();

            this.nestlevel = nestlevel;

            foreach (IHtmlNode node in nodes)
            {
                if (string.Equals(node.ElementName, "table", StringComparison.OrdinalIgnoreCase))
                {
                    //如果当前节点是表，则添加

                    tables.Add(new HtmlTable(node, path, nestlevel, tables.Count));
                }
                else
                {
                    //否则递归查看当前节点的子节点

                    SearchTable(node, tables, path, nestlevel);
                }
            }
        }

        private void SearchTable(IHtmlNode node, List<IHtmlTable> tables, string path, int nestlevel)
        {
            foreach (IHtmlNode subnode in node.Nodes)
            {
                if (string.Equals(subnode.ElementName, "table", StringComparison.OrdinalIgnoreCase))
                {
                    //如果当前节点是表，则添加

                    tables.Add(new HtmlTable(subnode, path, nestlevel, tables.Count));
                }
                else
                {
                    //否则递归查看当前节点的子节点

                    SearchTable(subnode, tables, path, nestlevel);
                }
            }
        }

        public HtmlTableCollection(List<IHtmlTable> tables, int nestlevel)
        {
            this.nestlevel = nestlevel;
            this.tables = tables;
        }



        public IHtmlTable this[int index]
        {
            get
            {
                return tables[index];
            }
        }

        public int Count
        {
            get { return tables.Count; }
        }

        public IHtmlTable SearchTable(string path)
        {
            // /1.1.1/1

            // /1

            if (string.IsNullOrEmpty(path))
                return null;

            string[] paths = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

            string currentpath = paths[nestlevel];

            if (nestlevel > paths.Length - 1)
                throw new Exception("path format error.");

            if (nestlevel < paths.Length - 1)
                return GetCurrentCell(currentpath).Tables.SearchTable(path);



            string[] subpaths = currentpath.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

            int tableindex = 0;

            if (!int.TryParse(subpaths[0], out tableindex))
                throw new Exception("path format error.");

            if (tableindex > tables.Count - 1)
                throw new Exception("path table format error.");

            IHtmlTable table = tables[tableindex];

            return table;
        }

        public IHtmlCell SearchCell(string path)
        {
            // /1.1.1/2.2.2

            // /1.1.1

            if (string.IsNullOrEmpty(path))
                return null;

            string[] paths = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

            if (nestlevel > paths.Length - 1)
                throw new Exception("path format error.");

            string currentpath = paths[nestlevel];

            if (nestlevel < paths.Length - 1)
                return GetCurrentCell(currentpath).Tables.SearchCell(path);
            else
                return GetCurrentCell(currentpath);
        }

        public IHtmlRow SearchRow(string path)
        {
            // /1.1.1/2.2

            // /1.1

            if (string.IsNullOrEmpty(path))
                return null;

            string[] paths = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

            if (nestlevel > paths.Length - 1)
                throw new Exception("path format error.");

            string currentpath = paths[nestlevel];

            if (nestlevel < paths.Length - 1)
                return GetCurrentCell(currentpath).Tables.SearchRow(path);

            IHtmlTable table = SearchTable(path);


            string[] subpaths = currentpath.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

            if (subpaths.Length < 2)
                throw new Exception("error path format.");

            int rowindex = 0;

            if (!int.TryParse(subpaths[1], out rowindex))
                throw new Exception("path format error.");

            if (rowindex > table.Rows.Length - 1)
                throw new Exception("path row format error.");

            IHtmlRow row = table.Rows[rowindex];

            return row;
        }

        private IHtmlCell GetCurrentCell(string currentpath)
        {
            if (string.IsNullOrEmpty(currentpath))
                return null;

            string[] subpaths = currentpath.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

            if (subpaths.Length < 3)
                throw new Exception("error path format.");

            int tableindex = 0;

            if (!int.TryParse(subpaths[0], out tableindex))
                throw new Exception("path format error.");

            if (tableindex > tables.Count - 1)
                throw new Exception("path table format error.");

            IHtmlTable table = tables[tableindex];

            int rowindex = 0;

            if (!int.TryParse(subpaths[1], out rowindex))
                throw new Exception("path format error.");

            if (rowindex > table.Rows.Length - 1)
                throw new Exception("path row format error.");

            IHtmlRow row = table.Rows[rowindex];

            int cellindex = 0;

            if (!int.TryParse(subpaths[2], out cellindex))
                throw new Exception("path format error.");

            if (cellindex > row.Cells.Length - 1)
                throw new Exception("path cell format error.");

            IHtmlCell cell = row.Cells[cellindex];

            return cell;
        }

        public string Serialize()
        {
            StringBuilder builder = new StringBuilder();
            foreach (IHtmlTable table in tables)
            {
                builder.Append(table.Serialize());
            }
            return builder.ToString();
        }


        #region IEnumerable<IHtmlTable> 成员

        public IEnumerator<IHtmlTable> GetEnumerator()
        {
            return this;
        }

        #endregion

        #region IEnumerable 成员

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this;
        }

        #endregion

        #region IEnumerator<IHtmlTable> 成员

        public IHtmlTable Current
        {
            get
            {
                return this[index];
            }
        }

        #endregion

        #region IDisposable 成员

        public void Dispose()
        {
            Reset();
        }

        #endregion

        #region IEnumerator 成员

        object System.Collections.IEnumerator.Current
        {
            get { return this[index]; }
        }

        public bool MoveNext()
        {
            if (index >= tables.Count - 1)
                return false;

            index++;

            return true;
        }

        public void Reset()
        {
            index = -1;
        }

        #endregion
    }
}
